package org.example.springoauth2.securitycommon.config.resource;

import org.example.springoauth2.securitycommon.config.authenticate.OtherAuthorizationSecurityConfiguration;
import org.example.springoauth2.securitycommon.entity.JdbcUser;
import org.example.springoauth2.securitycommon.entity.JdbcUserAuth;
import org.example.springoauth2.securitycommon.entity.SysUser;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 提取认证信息
 *
 * @author hzq
 * @date 2021/9/13 17:41
 */
public class EnhanceUserAuthenticationConverter implements UserAuthenticationConverter {

    private static final String N_A = "N/A";

    @Override
    public Map<String, ?> convertUserAuthentication(Authentication userAuthentication) {
        Map<String, Object> response = new LinkedHashMap<>();
        response.put(USERNAME, userAuthentication.getName());
        if (userAuthentication.getAuthorities() != null && !userAuthentication.getAuthorities().isEmpty()) {
            response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(userAuthentication.getAuthorities()));
        }
        return response;
    }

    /**
     * @see OtherAuthorizationSecurityConfiguration#tokenEnhancer()
     */
    @Override
    public Authentication extractAuthentication(Map<String, ?> map) {
        if (map.containsKey(USERNAME)) {
            Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
            /*
             * additionalInfo.put("jdbcUser_id", sysUser.getJdbcUser().getId());
             * additionalInfo.put("jdbcUser_nickname", sysUser.getJdbcUser().getNickname());
             * additionalInfo.put("jdbcUser_tenantId", sysUser.getJdbcUser().getTenantId());
             * additionalInfo.put("jdbcUser_unionId", sysUser.getJdbcUser().getUnionId());
             * additionalInfo.put("jdbcUser_userType", sysUser.getJdbcUser().getUserType());
             * additionalInfo.put("jdbcUser_gender", sysUser.getJdbcUser().getGender());
             * additionalInfo.put("jdbcUser_jdbcUserAuth_authType", sysUser.getJdbcUser().getJdbcUserAuth().getAuthType());
             * additionalInfo.put("jdbcUser_jdbcUserAuth_key", sysUser.getJdbcUser().getJdbcUserAuth().getKey());
             */
            JdbcUser jdbcUser = JdbcUser.builder()
                    .id((Integer) map.get("jdbcUser_id"))
                    .nickname((String) map.get("jdbcUser_nickname"))
                    .tenantId((Integer) map.get("jdbcUser_tenantId"))
                    .unionId((String) map.get("jdbcUser_unionId"))
                    .userType((String) map.get("jdbcUser_userType"))
                    .gender((String) map.get("jdbcUser_gender"))
                    .build();
            JdbcUserAuth jdbcUserAuth = JdbcUserAuth.builder()
                    .unionId(jdbcUser.getUnionId())
                    .tenantId(jdbcUser.getTenantId())
                    .authType((String) map.get("jdbcUser_jdbcUserAuth_authType"))
                    .key((String) map.get("jdbcUser_jdbcUserAuth_key"))
                    .secret(N_A)
                    .build();
            jdbcUser.setJdbcUserAuth(jdbcUserAuth);
            jdbcUser.setAuthorities(authorities);
            SysUser sysUser = new SysUser(jdbcUser);
            return new UsernamePasswordAuthenticationToken(sysUser, N_A, authorities);
        }
        return null;
    }

    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
        Object authorities = map.get(AUTHORITIES);
        if (authorities instanceof String) {
            return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
        }
        if (authorities instanceof Collection) {
            return AuthorityUtils.commaSeparatedStringToAuthorityList(
                    StringUtils.collectionToCommaDelimitedString((Collection<?>) authorities));
        }
        return AuthorityUtils.NO_AUTHORITIES;
    }
}
